package interview.juc;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @Author: zhangrongqing
 * @Date: 2019/11/28 17:04
 */
public class PrintABC {
    ReentrantLock lock = new ReentrantLock();
    Condition conditionA = lock.newCondition();
    Condition conditionB = lock.newCondition();
    Condition conditionC = lock.newCondition();

    int num = 0;

    class A implements Runnable {
        String str;
        Condition startCondition;
        Condition nextCondition;

        public A(String str, Condition startCondition, Condition nextCondition) {
            this.str = str;
            this.startCondition = startCondition;
            this.nextCondition = nextCondition;
        }

        @Override
        public void run() {
            lock.lock();
            try {
                for (int i = 0; i < 10; i++) {
                    try {
                        if (num % 3 != 0) {
                            startCondition.await();
                        }
                    } catch (InterruptedException e) {
                    }
                    System.out.println(str);
                    nextCondition.signalAll();
                    num++;
                }
            } finally {
                lock.unlock();
            }
        }
    }

    class B implements Runnable {
        String str;
        Condition startCondition;
        Condition nextCondition;

        public B(String str, Condition startCondition, Condition nextCondition) {
            this.str = str;
            this.startCondition = startCondition;
            this.nextCondition = nextCondition;
        }

        @Override
        public void run() {
            lock.lock();
            try {
                for (int i = 0; i < 10; i++) {
                    try {
                        if (num % 3 != 1) {
                            startCondition.await();
                        }
                    } catch (InterruptedException e) {
                    }
                    System.out.println(str);
                    nextCondition.signalAll();
                    num++;
                }
            } finally {
                lock.unlock();
            }
        }
    }

    class C implements Runnable {
        String str;
        Condition startCondition;
        Condition nextCondition;

        public C(String str, Condition startCondition, Condition nextCondition) {
            this.str = str;
            this.startCondition = startCondition;
            this.nextCondition = nextCondition;
        }

        @Override
        public void run() {
            lock.lock();
            try {
                for (int i = 0; i < 10; i++) {
                    try {
                        if (num % 3 != 2) {
                            startCondition.await();
                        }
                    } catch (InterruptedException e) {
                    }
                    System.out.println(str);
                    nextCondition.signalAll();
                    num++;
                }
            } finally {
                lock.unlock();
            }
        }
    }

    public void run() {
        A a = new A("A", conditionA, conditionB);
        B b = new B("B", conditionB, conditionC);
        C c = new C("C", conditionC, conditionA);
        new Thread(a).start();
        new Thread(b).start();
        new Thread(c).start();

    }

    public static void main(String[] args) {
        new PrintABC().run();
    }


}


